package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"

	"laravel-vue-admin/socket/api"
	"laravel-vue-admin/socket/auth"
	"laravel-vue-admin/socket/client"
	"laravel-vue-admin/socket/config"
	"laravel-vue-admin/socket/hub"

	"github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		// 在生产环境中应该检查Origin
		return true
	},
}

func main() {
	// 加载配置
	cfg, err := config.LoadConfig("config.yaml")
	if err != nil {
		log.Fatalf("加载配置失败: %v", err)
	}

	// 初始化认证
	if err := auth.Init(cfg); err != nil {
		log.Fatalf("初始化认证失败: %v", err)
	}
	defer auth.Close()

	// 创建Hub
	h := hub.NewHub()
	go h.Run()

	// 创建API服务
	apiService := api.NewAPI(h)
	apiService.RegisterRoutes()

	// WebSocket端点
	http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
		handleWebSocket(h, w, r)
	})

	// 健康检查端点
	http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("OK"))
	})

	// 在线用户统计端点（保留兼容性）
	http.HandleFunc("/stats", func(w http.ResponseWriter, r *http.Request) {
		onlineUsers := h.GetOnlineUsers()
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		w.Write([]byte(fmt.Sprintf(`{"online_users": %d, "users": %v}`, len(onlineUsers), onlineUsers)))
	})

	// 启动服务器
	addr := cfg.GetAddress()
	log.Printf("WebSocket服务器启动在 %s", addr)

	// 优雅关闭
	go func() {
		sigChan := make(chan os.Signal, 1)
		signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
		<-sigChan
		log.Println("正在关闭服务器...")
		auth.Close()
		os.Exit(0)
	}()

	if err := http.ListenAndServe(addr, nil); err != nil {
		log.Fatalf("服务器启动失败: %v", err)
	}
}

func handleWebSocket(h *hub.Hub, w http.ResponseWriter, r *http.Request) {
	// 验证Token
	claims, err := auth.AuthenticateWebSocket(r)
	if err != nil {
		log.Printf("认证失败: %v", err)
		http.Error(w, "认证失败", http.StatusUnauthorized)
		return
	}

	// 升级到WebSocket连接
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Printf("WebSocket升级失败: %v", err)
		return
	}

	// 获取用户ID
	userID, err := claims.GetUserID()
	if err != nil {
		log.Printf("获取用户ID失败: %v", err)
		http.Error(w, "认证失败", http.StatusUnauthorized)
		return
	}

	// 创建客户端
	c := client.NewClient(conn, userID, h)
	h.Register(c)

	// 启动读写协程
	go c.WritePump()
	go c.ReadPump()

	log.Printf("新客户端连接: UserID=%d, ClientID=%d", userID, c.ID)
}

